package com.bicon.botu.account.api;

import com.bicon.botu.account.common.AccountConstants;
import com.bicon.botu.account.common.utils.Encrypt;
import com.bicon.botu.account.dto.AccountInfoDTO;
import com.bicon.botu.account.dto.UserInfoParam;
import com.bicon.botu.account.entity.AccountInfo;
import com.bicon.botu.account.entity.AccountThird;
import com.bicon.botu.account.handler.AccountHandler;
import com.bicon.botu.account.param.RegisterParam;
import com.bicon.botu.account.service.AccountThirdService;
import com.bicon.botu.account.service.IAccountService;
import com.bicon.botu.core.base.common.BusinessException;
import com.bicon.botu.core.base.common.Constants;
import com.bicon.botu.core.base.common.controller.BaseController;
import com.bicon.botu.core.base.common.entity.BaseResult;
import com.bicon.botu.core.base.common.utils.IdGenerator;
import com.bicon.botu.core.base.common.utils.StringUtils;
import com.bicon.botu.core.base.validate.ValidateUtils;
import com.bicon.botu.third.util.StringUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;


/**
 * 账户管理、用户注册、登录、发短信、校验
 */
@Slf4j
@RestController
@RequestMapping("/api/account")
@Api("账户管理")
public class AccountApi extends BaseController {

    @Autowired
    private IAccountService iAccountService;

    @Autowired
    private AccountHandler accountHandler;


    @Autowired
    private AccountThirdService accountThirdService;

    /**
     * 用户注册
     *
     * @param account  账号
     * @param password 密码
     * @param code     验证码
     * @param source
     * @return
     */
    @ApiOperation("注册接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "account", value = "手机号", required = true, paramType = "query"),
            @ApiImplicitParam(name = "password", value = "密码", required = true, paramType = "query"),
            @ApiImplicitParam(name = "code", value = "验证码", required = true, paramType = "query"),
            @ApiImplicitParam(name = "source", value = "来源(1：android、2：ios、3：web)", required = true, paramType = "query", dataType = "int")
    })
    @PostMapping(value = "/static/register")
    public BaseResult register(@RequestParam String account,
                               @RequestParam String password,
                               @RequestParam String code,
                               @RequestParam int source) {
        if (StringUtils.isAnyEmpty(account, password, code)) {
            return sendResult400("参数不能为空");
        }

        if (!ValidateUtils.isPhone(account)) {
            return sendResult400("手机号码格式不正确");
        }
        //检查账号是否存在  移动端 登录类型为1
        AccountInfoDTO accountInfoDTO = iAccountService.detail(account, 1);
        if (null != accountInfoDTO) {
            return new BaseResult(Constants.RESPONSE_CODE_602, "该手机号已注册，请直接登录！");
        }
        //检查验证码是否正确
        if (!iAccountService.verifySmsCode(account, code, 1)) {
            return new BaseResult(Constants.RESPONSE_CODE_405, "验证码错误或失效！");
        }
        //通过校验，注册，移动端注册成功直接登录
        accountInfoDTO = iAccountService.register(account, password, null, null, source);
        if (null != accountInfoDTO) {
            return refreshToken(accountInfoDTO);
        }
        //注册失败
        return sendResult500();
    }

    /**
     * 验证码登录
     *
     * @param account 账号
     * @param code    验证码
     * @return
     */
    @ApiOperation("验证码登录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "account", value = "手机号", required = true, paramType = "query"),
            @ApiImplicitParam(name = "code", value = "验证码", required = true, paramType = "query"),
    })
    @PostMapping(value = "/static/login-smscode")
    public BaseResult loginBySmsCode(@RequestParam String account, @RequestParam String code) {
        if (StringUtils.isAnyEmpty(account, code)) {
            return sendResult400("参数不能为空");
        }
        if (!ValidateUtils.isPhone(account)) {
            return sendResult400("手机号码格式不正确");
        }
        //校验手机验证码是否正确、过期
        //检查验证码是否正确
        if (!iAccountService.verifySmsCode(account, code, 1)) {
            return new BaseResult(Constants.RESPONSE_CODE_405, "验证码错误或失效！");
        }
        //校验该账号是否存在
        AccountInfoDTO accountInfoDTO = iAccountService.detail(account, 1);
        //如果账号不存在 直接系统注册并添加新账号
        if (null == accountInfoDTO) {
            //注册
            accountInfoDTO = iAccountService.register(account, "yjwl123456", null, null, 1);
        }
        if (accountInfoDTO.getEnable().equals(AccountConstants.ENABLE_FALSE)) {
            //判断账号的状态
            return new BaseResult(Constants.RESPONSE_CODE_405, "该账号已被禁用！");
        }


        return refreshToken(accountInfoDTO);
    }

    /**
     * 校验验证码
     *
     * @param account 账号
     * @param code    验证码
     * @return
     */
    @ApiOperation("校验验证码")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "account", value = "手机号", required = true, paramType = "query"),
            @ApiImplicitParam(name = "code", value = "验证码", required = true, paramType = "query"),
    })
    @RequestMapping(value = "/static/verifyCode", method = RequestMethod.POST)
    public BaseResult verifyCode(@RequestParam String account, @RequestParam String code) {
        if (StringUtils.isAnyEmpty(account, code)) {
            return sendResult400("参数不能为空");
        }
        if (!iAccountService.verifySmsCode(account, code, 1)) {
            return new BaseResult(Constants.RESPONSE_CODE_405, "验证码错误或失效！");
        }
        return sendResult200();
    }


    /**
     * 密码登录
     *
     * @param account  账号
     * @param password 密码
     * @return
     */
    @ApiOperation("密码登录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "account", value = "手机号", required = true, paramType = "query"),
            @ApiImplicitParam(name = "password", value = "密码", required = true, paramType = "query"),
    })
    @PostMapping(value = "/static/login")
    public BaseResult login(@RequestParam String account, @RequestParam String password) {
        if (StringUtils.isAnyEmpty(account, password)) {
            return sendResult400("参数不能为空");
        }
        if (!ValidateUtils.isPhone(account)) {
            return sendResult400("手机号码格式不正确");
        }
        if(!ValidateUtils.regular(password, AccountConstants.USERPASSWORD)){
            return sendResult400("请设置至少8位的数字和字母的组合密码");
        }
        //检查账号是否存在
        AccountInfoDTO accountInfoDTO = iAccountService.detail(account, 1);
        if (null == accountInfoDTO) {
            return new BaseResult(Constants.RESPONSE_CODE_602, "该账号不存在！");
        }
        if (accountInfoDTO.getEnable().equals(AccountConstants.ENABLE_FALSE)) {
            //判断账号的状态
            return new BaseResult(Constants.RESPONSE_CODE_405, "该账号已被禁用！");
        } else if (!accountInfoDTO.getPassword().equals(Encrypt.md5ForAuth(password, accountInfoDTO.getSalt()))) {
            //密码错误
            return new BaseResult(Constants.RESPONSE_CODE_403, "密码错误");
        }
        return refreshToken(accountInfoDTO);
    }


    /**
     * 移动端发送验证码---注册、忘记密码使用
     *
     * @param account 账号
     * @param flag    1:登录，2：注册，3：忘记密码
     * @return
     */
    @ApiOperation("发送验证码")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "account", value = "手机号", required = true, paramType = "query"),
            @ApiImplicitParam(name = "flag", value = "类型( 1:登录，2：注册，3：忘记密码,4:发送验证码)", required = true, paramType = "query", dataType = "int")
    })
    @PostMapping(value = "/static/sendSms")
    public BaseResult sendSms(String account, int flag) {

        if (StringUtils.isEmpty(account)) {
            return sendResult400("参数不能为空");
        }
        if (!ValidateUtils.isPhone(account)) {
            return sendResult400("手机号码格式不正确");
        }
        //快捷登录和修改手机号 不检查 手机号。直接发送。
        // 忘记密码和注册 发送短信需要校验。检查账号是否存在
        if (flag == 1) {
            //登录检查
            if (!iAccountService.checkAccountExist(account, AccountConstants.ACCOUNT_LOGIN_TYPE_APP)) {
                throw new BusinessException(Constants.RESPONSE_CODE_602, "该账号不存在！");
            }
        } else if (flag == 2) {
            //注册检查
            if (iAccountService.checkAccountExist(account, AccountConstants.ACCOUNT_LOGIN_TYPE_APP)) {
                throw new BusinessException(Constants.RESPONSE_CODE_602, "该账号已存在，请登录!");
            }
        } else if (flag == 3) {
            //忘记密码检查
            if (!iAccountService.checkAccountExist(account, AccountConstants.ACCOUNT_LOGIN_TYPE_APP)) {
                throw new BusinessException(Constants.RESPONSE_CODE_602, "该账号不存在！");
            }
        } else if (flag == 4) {
            //短信测试并返回，不走短信平台
            return sendResult200(iAccountService.sendSmsCodeString(account, 1));
        } else {
            return sendResult500("传递的类型不对");
        }
        return sendResult200(iAccountService.sendSmsCodeString(account, 1));
        //正式环境需要放开下面代码，
//        if (iAccountService.sendSmsCode(account, 1)) {
//            return sendResult200();
//        }
//        return sendResult500();
    }


    /**
     * 忘记密码接口
     *
     * @param account  账号
     * @param password 密码
     * @param code     验证码
     * @return
     */
    @ApiOperation("忘记密码接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "account", value = "手机号", required = true, paramType = "query"),
            @ApiImplicitParam(name = "password", value = "密码", required = true, paramType = "query"),
            @ApiImplicitParam(name = "code", value = "验证码", required = true, paramType = "query")
    })
    @PostMapping(value = "/static/forgetpwd")
    public BaseResult forgetPassword(@RequestParam String account, @RequestParam String password, @RequestParam String code) {
        if (StringUtils.isAnyEmpty(account, password,code)) {
            return sendResult400("参数不能为空");
        }
        if (!ValidateUtils.isPhone(account)) {
            return sendResult400("手机号码格式不正确");
        }

        if(!ValidateUtils.regular(password, AccountConstants.USERPASSWORD)){
            return sendResult400("请设置至少8位的数字和字母的组合密码");
        }
        //检查账号是否存在
        AccountInfoDTO accountInfoDTO = iAccountService.detail(account, AccountConstants.ACCOUNT_LOGIN_TYPE_APP);
        if (null == accountInfoDTO) {
            return new BaseResult(Constants.RESPONSE_CODE_602, "该账号不存在！");
        }
        if (accountInfoDTO.getEnable().equals(AccountConstants.ENABLE_FALSE)) {
            //判断账号的状态
            return new BaseResult(Constants.RESPONSE_CODE_405, "该账号已被禁用！");
        }
        //检查验证码是否正确
        if (!iAccountService.verifySmsCode(account, code, AccountConstants.ACCOUNT_LOGIN_TYPE_APP)) {
            return new BaseResult(Constants.RESPONSE_CODE_405, "手机号或验证码错误！");
        }
        //修改密码操作
        if (iAccountService.forgetPassByAccout(account, Encrypt.md5ForAuth(password, accountInfoDTO.getSalt()), 1)) {
            return sendResult200();
        }
        return sendResult500();
    }

    /**
     * 修改手机号码
     *
     * @param userId  用户id
     * @param account 新手机号
     * @param code    验证码
     * @return
     */
    @ApiOperation("修改手机号码")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "account", value = "新手机号", required = true, paramType = "query"),
            @ApiImplicitParam(name = "userId", value = "用户id", required = true, paramType = "query"),
            @ApiImplicitParam(name = "code", value = "验证码", required = true, paramType = "query")
    })
    @PostMapping(value = "/updatePhone")
    public BaseResult updatePhone(@RequestParam String userId, @RequestParam String account, @RequestParam String code) {
        //检查账号是否存在
        AccountInfoDTO accountInfoDTO = iAccountService.detailInfo(userId, 1);
        if (null == accountInfoDTO) {
            return new BaseResult(Constants.RESPONSE_CODE_602, "该账号不存在！");
        }
        if (accountInfoDTO.getEnable().equals(AccountConstants.ENABLE_FALSE)) {
            //判断账号的状态
            return new BaseResult(Constants.RESPONSE_CODE_405, "该账号已被禁用！");
        }
        //检查验证码是否正确
        if (!iAccountService.verifySmsCode(account, code, AccountConstants.ACCOUNT_LOGIN_TYPE_APP)) {
            return new BaseResult(Constants.RESPONSE_CODE_405, "验证码错误或失效！");
        }
        //修改密码账号操作
        if (iAccountService.update(userId, account, null, 1)) {
            return sendResult200();
        }
        return sendResult500();
    }


    /**
     * 修改密码
     *
     * @param account     账号
     * @param oldPassword 原始密码
     * @param newPassword 新密码
     * @return
     */
    @ApiOperation("修改密码")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "account", value = "手机号", required = true, paramType = "query"),
            @ApiImplicitParam(name = "oldPassword", value = "原始密码", required = true, paramType = "query"),
            @ApiImplicitParam(name = "newPassword", value = "新密码", required = true, paramType = "query")
    })
    @PostMapping(value = "/updatepwd")
    public BaseResult updatepwd(@RequestParam String account, @RequestParam String oldPassword, @RequestParam String newPassword) {
        //检查账号是否存在
        AccountInfoDTO accountInfoDTO = iAccountService.detail(account, 1);
        if (null == accountInfoDTO) {
            return new BaseResult(Constants.RESPONSE_CODE_602, "该账号不存在！");
        }
        if (accountInfoDTO.getEnable().equals(AccountConstants.ENABLE_FALSE)) {
            //判断账号的状态
            return new BaseResult(Constants.RESPONSE_CODE_405, "该账号已被禁用！");
        }
        //检查老密码是否正确
        if (!accountInfoDTO.getPassword().equals(Encrypt.md5ForAuth(oldPassword, accountInfoDTO.getSalt()))) {
            return new BaseResult(Constants.RESPONSE_CODE_405, "原始密码错误！");
        }
        //修改密码操作
        if (iAccountService.forgetPassByAccout(account, Encrypt.md5ForAuth(newPassword, accountInfoDTO.getSalt()), 1)) {
            return sendResult200();
        }
        return sendResult500();
    }


    /**
     * 第三方登录
     *
     * @param thirdId    账号
     * @param thirdParty 第三方平台（1：微信，2：QQ，3：新浪微博）
     * @return
     */
    @ApiOperation("第三方登录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "thirdId", value = "第三方id", required = true, paramType = "query"),
            @ApiImplicitParam(name = "thirdParty", value = "第三方平台（1：微信，2：QQ，3：新浪微博）", required = true, paramType = "query", dataType = "int")
    })
    @PostMapping(value = "/static/login-third")
    public BaseResult loginThird(@RequestParam String thirdId, @RequestParam int thirdParty) {

        if(StringUtils.isEmpty(thirdId)){
            return new BaseResult(Constants.RESPONSE_CODE_602, "第三方id不能为空");
        }
        AccountThird accountThird = accountThirdService.getAccountThird(thirdId, thirdParty);
        if (null == accountThird) {
            return new BaseResult(Constants.RESPONSE_CODE_602, "该账号不存在,请关联账号注册");
        }
        AccountInfo accountInfo = iAccountService.selectById(accountThird.getAccountId());
        AccountInfoDTO accountInfoDTO = new AccountInfoDTO();
        BeanUtils.copyProperties(accountInfo, accountInfoDTO);
        if (null == accountInfoDTO) {
            return new BaseResult(Constants.RESPONSE_CODE_602, "该账号不存在,请关联账号注册");
        }
        if (accountInfoDTO.getEnable().equals(AccountConstants.ENABLE_FALSE)) {
            //判断账号的状态
            return new BaseResult(Constants.RESPONSE_CODE_405, "该账号已被禁用！");
        }
        return refreshToken(accountInfoDTO);
    }


    /**
     * 关联账号
     *
     * @param registerParam 注册参数实体类
     * @return
     */
    @ApiOperation("关联账号(第三方注册)")
    @PostMapping(value = "/static/register-third")
    public BaseResult registerThird(@RequestBody RegisterParam registerParam) {

        if (StringUtils.isEmpty(registerParam.getCode())) {
            return new BaseResult(Constants.RESPONSE_CODE_602,"验证码不能为空");
        }
        if (!ValidateUtils.isPhone(registerParam.getAccount())) {
            return new BaseResult(Constants.RESPONSE_CODE_602,"手机号码格式不正确");
        }
        if(StringUtils.isEmpty(registerParam.getThirdId())){
            return new BaseResult(Constants.RESPONSE_CODE_602, "第三方id不能为空");
        }
        //不存在，则校验验证码和账号
        //检查验证码是否正确
        if (!iAccountService.verifySmsCode(registerParam.getAccount(), registerParam.getCode(), 1)) {
            return new BaseResult(Constants.RESPONSE_CODE_405, "验证码错误或失效！");
        }
        AccountThird accountThird = accountThirdService.getAccountThird(registerParam.getThirdId(), registerParam.getThirdParty());
        if (null != accountThird) {
            return new BaseResult(Constants.RESPONSE_CODE_602, "该账号已关联，请直接登录！");
        }
        //通过校验，注册关联
        //通过校验，注册，移动端注册成功直接登录
        AccountInfoDTO accountInfoDTO = iAccountService.registerBind(registerParam);
        if (null != accountInfoDTO) {
            return refreshToken(accountInfoDTO);
        }
        //注册失败
        return sendResult500();
    }

    /**
     * 获取用户角色列表
     *
     * @return
     */
    @ApiOperation("获取用户角色列表")
    @GetMapping(value = "/getAccountRole")
    public BaseResult getAccountRole() {
        return iAccountService.getAccountRole(getUserId());
    }

    /**
     * 刷新token，并返回token 等信息
     *
     * @param accountInfoDTO
     * @return
     */
    private BaseResult refreshToken(AccountInfoDTO accountInfoDTO) {
        String token = IdGenerator.create24Id();
        if (accountHandler.initToken(accountInfoDTO.getAccount(), token, accountInfoDTO.getId(), null)) {
            //将id 、和 token ，账号返回
            return sendResult200(new AccountInfoDTO(accountInfoDTO.getAccount(), token, accountInfoDTO.getId()));
        } else {
            return sendResult500();
        }
    }


}
